﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Tian.Common.Sort;

namespace Tian.Common.Base
{
    /// <summary>
    /// 文件基础操作封装
    /// </summary>
    public class FileUtil
    {
        /// <summary>
        /// 获取该文件路径下的所有文件
        /// </summary>
        /// <param name="path">文件路径</param>
        public List<FileInfo> GetAllFilesInPath(string path)
        {
            List<FileInfo> files = new List<FileInfo>();
            DirectoryInfo dir = new DirectoryInfo(path);
            FileInfo[] file = dir.GetFiles();
            files.AddRange(file);
            return files;
        }

        /// <summary>
        /// 获取该文件路径下的所有文件
        /// </summary>
        /// <param name="path">文件路径</param>
        public List<FileInfo> GetAllFilesInPath(string path, List<string> suffixs, bool isAsc)
        {
            DirectoryInfo dir = new DirectoryInfo(path);
            List<FileInfo> files = dir.GetFiles().Where(n =>
            {
                string[] list = n.Name.Split('.');
                string houzhui = list[list.Length - 1].ToLower();
                if (suffixs.Contains(houzhui))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }).ToList();
            FileSort fileIComparer = new FileSort();
            //文件排序
            if (isAsc)
            {
                fileIComparer.FileSortByNameAsc(ref files);
            }
            else
            {
                fileIComparer.FileSortByNameDesc(ref files);
            }
            return files;
        }
        /// <summary>
        /// 获取该文件下的某个类型的所有文件（包括子文件夹下文件）
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="type">文件类型</param>
        public List<FileInfo> GetAllFilesInPath(string path, string type)
        {
            List<FileInfo> fileAll = new List<FileInfo>();
            DirectoryInfo dir = new DirectoryInfo(path);
            DirectoryInfo[] dirs = dir.GetDirectories();
            for (int i = 0; i < dirs.Length; i++)
            {
                FileInfo[] file = dirs[i].GetFiles();
                fileAll.AddRange(file);
            }
            List<FileInfo> fileData = fileAll.FindAll(t =>
            {
                string[] list = t.Name.Split('.');
                string houzhui = list[list.Length - 1].ToLower();
                if (type.ToLower() == houzhui)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            });
            return fileData;
        }

        /// <summary>
        /// 获取这些路径下的所有文件
        /// </summary>
        /// <param name="paths">路径集合</param>
        /// <returns>文件集合</returns>
        public List<FileInfo> GetAllFilesInPaths(List<DirectoryInfo> paths)
        {
            List<FileInfo> files = new List<FileInfo>();
            foreach (DirectoryInfo item in paths)
            {
                FileInfo[] file = item.GetFiles();
                files.AddRange(file);
            }
            return files;
        }

        /// <summary>
        /// 获取夹文件路径下所有文件夹,包括本身文件夹
        /// </summary>
        /// <param name="path">文件夹路径</param>
        /// <returns>文件夹集合</returns>
        public List<DirectoryInfo> GetAllFoldersInPath(string path)
        {
            List<DirectoryInfo> folders = new List<DirectoryInfo>();
            DirectoryInfo dir = new DirectoryInfo(path);
            folders.Add(dir);
            DirectoryInfo[] dirs = dir.GetDirectories();
            folders.AddRange(dirs);
            for (int i = 0; i < dirs.Length; i++)
            {
                DirectoryInfo dirone = new DirectoryInfo(dirs[i].FullName);
                DirectoryInfo[] dirsone = dirone.GetDirectories();
                if (dirsone.Length > 0)
                {
                    GetFoldersInPath(dirs[i].FullName, ref folders);//
                }
            }
            return folders;
        }

        private void GetFoldersInPath(string path, ref List<DirectoryInfo> folders)
        {
            DirectoryInfo dir = new DirectoryInfo(path);
            DirectoryInfo[] dirs = dir.GetDirectories();
            if (dirs.Length > 0)
            {
                folders.AddRange(dirs);
                for (int i = 0; i < dirs.Length; i++)
                {
                    DirectoryInfo dirone = new DirectoryInfo(dirs[i].FullName);
                    DirectoryInfo[] dirsone = dirone.GetDirectories();
                    if (dirsone.Length > 0)
                    {
                        GetFoldersInPath(dirs[i].FullName, ref folders);//回调本身获取路径
                    }
                }
            }
        }


        /// <summary>
        /// 判断是否存在该文件名的文件，返回文件数量
        /// </summary>
        /// <param name="filename">文件名称</param>
        /// <param name="files">文件集合</param>
        /// <returns></returns>
        public int IsExistFile(string filename, List<FileInfo> files)
        {
            List<FileInfo> files_one = files.FindAll(t => t.Name.Contains(filename));
            int count = files_one.Count;
            return count;
        }

        /// <summary>
        /// 判断是否存在该文件名的文件，并重命名及移动文件位置,返回新文件名称
        /// </summary>
        /// <param name="filename">文件名称</param>
        /// <param name="files">文件集合</param>
        /// <param name="defaultname">默认文件名称</param>
        /// <param name="newname">新名称</param>
        /// <param name="newpath">新地址</param>
        /// <returns>文件名称</returns>
        public string IsExistFile(string filename, List<FileInfo> files, string defaultname, string newname, string newpath)
        {
            string name = defaultname;
            //防止文件名中间带有空格
            List<FileInfo> files_one = files.FindAll(t => t.Name.Replace(" ", "").Contains(filename));
            if (files_one.Count == 0)
            {
                name = defaultname;
            }
            else if (files_one.Count == 1)
            {
                string[] strs = files_one[0].Name.Split('.');
                string houzhui = strs[strs.Length - 1].ToLower();
                name = filename + "(" + newname + ")." + houzhui;
                //name = filename + "." + houzhui;
                files_one[0].MoveTo(newpath + "\\" + name);
            }
            else
            {
                name = "存在多条数据";
            }
            return name;
        }

        /// <summary>
        /// 更改文件夹下所有文件的后缀名
        /// </summary>
        /// <param name="startpath">初始的文件夹路径</param>
        /// <param name="endpath">移动的文件夹路径</param>
        /// <param name="suffix">文件后缀</param>
        public void ReNamePathFileSuffix(string startpath, string endpath, string suffix)
        {
            List<FileInfo> fileInfos = GetAllFilesInPath(startpath);
            for (int i = 0; i < fileInfos.Count; i++)
            {
                FileInfo file = fileInfos[i];
                string name = file.Name.Split('.')[0];
                fileInfos[i].CopyTo(endpath + "\\" + name + "." + suffix);
            }
        }
        /// <summary>
        /// 把json字符保存为json文件
        /// </summary>
        /// <param name="content">json字符</param>
        /// <param name="savepath">保存的文件名称全称（含路径）</param>
        public void StringToJsonFile(string content, string savepath)
        {
            FileStream fileStream = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
            StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.UTF8);
            streamWriter.WriteLine(content);
            streamWriter.Close();
            streamWriter.Dispose();
            fileStream.Close();
            fileStream.Dispose();
        }
        /// <summary>
        /// 将byte数组转换为文件并保存到指定地址
        /// </summary>
        /// <param name="buffer">byte数组</param>
        /// <param name="savepath">保存地址</param>
        public void BytesFile(byte[] buffer, string savepath)
        {
            if (File.Exists(savepath))
            {
                File.Delete(savepath);
            }
            FileStream filestream = new FileStream(savepath, FileMode.Create);
            BinaryWriter binarywriter = new BinaryWriter(filestream);
            binarywriter.Write(buffer, 0, buffer.Length);
            binarywriter.Close();
            binarywriter.Dispose();
            filestream.Close();
            filestream.Dispose();
        }

        /// <summary>
        /// 将文件转换为byte数组
        /// </summary>
        /// <param name="filepath">文件地址</param>
        /// <returns>转换后的byte数组</returns>
        public byte[] FileBytes(string filepath)
        {
            if (!System.IO.File.Exists(filepath))
            {
                return new byte[0];
            }
            FileInfo file = new FileInfo(filepath);
            byte[] buffer = new byte[file.Length];
            FileStream filestream = file.OpenRead();
            filestream.Read(buffer, 0, buffer.Length);
            filestream.Close();
            filestream.Dispose();
            return buffer;
        }


        /// <summary>
        /// 将文件转换为byte数组
        /// </summary>
        /// <param name="file">文件</param>
        /// <returns>转换后的byte数组</returns>
        public byte[] FileBytes(FileInfo file)
        {
            byte[] buffer = new byte[file.Length];
            FileStream filestream = file.OpenRead();
            filestream.Read(buffer, 0, buffer.Length);
            filestream.Close();
            filestream.Dispose();
            return buffer;
        }
        /// <summary>
        /// 将文件转换为可web上传的byte数组
        /// </summary>
        /// <param name="filepath">文件地址</param>
        /// <param name="boundary">访问方法的boundary</param>
        /// <param name="dic">额外参数</param>
        /// <returns>转换后的byte数组</returns>
        public byte[] WebFileBytes(string filepath, string boundary, Dictionary<string, string> dic)
        {
            FileInfo fileinfo = new FileInfo(filepath);
            string startBoundary = boundary + "\r\n";
            string endBoundary = boundary + "--\r\n";
            string contentDisposition = "Content-Disposition: form-data; name=\"upfile\"; filename=\"" + fileinfo.Name + "\"\r\n";
            string contentType = "Content-Type: multipart/form-data\r\n\r\n";//application/octet-stream、multipart/form-data
            MemoryStream memStream = new MemoryStream();
            //写入边界符
            byte[] start = Encoding.UTF8.GetBytes(startBoundary);
            memStream.Write(start, 0, start.Length);
            //写入描述
            byte[] disposition = Encoding.UTF8.GetBytes(contentDisposition);
            memStream.Write(disposition, 0, disposition.Length);
            //写入类型
            byte[] uptype = Encoding.UTF8.GetBytes(contentType);
            memStream.Write(uptype, 0, uptype.Length);
            //写入文件流
            byte[] file = FileBytes(fileinfo);
            memStream.Write(file, 0, file.Length);
            byte[] fileEnd = Encoding.UTF8.GetBytes("\r\n");
            memStream.Write(fileEnd, 0, fileEnd.Length);
            //写入额外参数
            foreach (var item in dic)
            {
                //写入边界符
                byte[] param_bjf = Encoding.UTF8.GetBytes(startBoundary);
                memStream.Write(param_bjf, 0, param_bjf.Length);
                //写入字段名
                string paramName = "Content-Disposition: form-data; name=\"" + item.Key + "\"\r\n\r\n";
                byte[] param_zdm = Encoding.UTF8.GetBytes(paramName);
                memStream.Write(param_zdm, 0, param_zdm.Length);
                //写入字段值
                string paramValue = item.Value + "\r\n";
                byte[] param_zdz = Encoding.UTF8.GetBytes(paramValue);
                memStream.Write(param_zdz, 0, param_zdz.Length);
            }
            //写入结束边界符
            byte[] end = Encoding.UTF8.GetBytes(endBoundary);
            memStream.Write(end, 0, end.Length);

            var upLoadBuffer = new byte[memStream.Length];
            memStream.Position = 0;//设置0否则读取不到，因为刚刚写入内存之后，位置恰好是在最后一位
            memStream.Read(upLoadBuffer, 0, upLoadBuffer.Length);
            memStream.Close();
            return upLoadBuffer;
        }
        /// <summary>
        /// 将文件转换为可web上传的byte数组
        /// </summary>
        /// <param name="fileinfo">文件</param>
        /// <param name="boundary">访问方法的boundary</param>
        /// <param name="dic">额外参数</param>
        /// <returns>转换后的byte数组</returns>
        public byte[] WebFileBytes(FileInfo fileinfo, string boundary, Dictionary<string, string> dic)
        {
            string startBoundary = boundary + "\r\n";
            string endBoundary = boundary + "--\r\n";
            string contentDisposition = "Content-Disposition: form-data; name=\"upfile\"; filename=\"" + fileinfo.Name + "\"\r\n";
            string contentType = "Content-Type: multipart/form-data\r\n\r\n";//application/octet-stream、multipart/form-data
            ;
            MemoryStream memStream = new MemoryStream();
            //写入边界符
            byte[] start = Encoding.UTF8.GetBytes(startBoundary);
            memStream.Write(start, 0, start.Length);
            //写入描述
            byte[] disposition = Encoding.UTF8.GetBytes(contentDisposition);
            memStream.Write(disposition, 0, disposition.Length);
            //写入类型
            byte[] uptype = Encoding.UTF8.GetBytes(contentType);
            memStream.Write(uptype, 0, uptype.Length);
            //写入文件流
            byte[] file = FileBytes(fileinfo);
            memStream.Write(file, 0, file.Length);
            byte[] fileEnd = Encoding.UTF8.GetBytes("\r\n");
            memStream.Write(fileEnd, 0, fileEnd.Length);
            //写入额外参数
            foreach (var item in dic)
            {
                //写入边界符
                byte[] param_bjf = Encoding.UTF8.GetBytes(startBoundary);
                memStream.Write(param_bjf, 0, param_bjf.Length);
                //写入字段名
                string paramName = "Content-Disposition: form-data; name=\"" + item.Key + "\"\r\n\r\n";
                byte[] param_zdm = Encoding.UTF8.GetBytes(paramName);
                memStream.Write(param_zdm, 0, param_zdm.Length);
                //写入字段值
                string paramValue = item.Value + "\r\n";
                byte[] param_zdz = Encoding.UTF8.GetBytes(paramValue);
                memStream.Write(param_zdz, 0, param_zdz.Length);
            }
            //写入结束边界符
            byte[] end = Encoding.UTF8.GetBytes(endBoundary);
            memStream.Write(end, 0, end.Length);

            var upLoadBuffer = new byte[memStream.Length];
            memStream.Position = 0;//设置0否则读取不到，因为刚刚写入内存之后，位置恰好是在最后一位
            memStream.Read(upLoadBuffer, 0, upLoadBuffer.Length);
            memStream.Close();
            return upLoadBuffer;
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="list">文件路径集合</param>
        public void DeleteFiles(List<string> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                FileInfo file = new FileInfo(list[i]);
                file.Delete();
            }
        }
    }
}
